
///|
/// 用两个整数表示的数学分数。
///
/// 字段：
///
/// * `numerator` : 分数的分子（上半部分）。
/// * `denominator` : 分数的分母（下半部分）。
///
/// 示例：
///
/// ```moonbit
/// let f1 = @amor2025/fraction/fraction.new(3, 4) // 3/4
/// let f2 = @amor2025/fraction/fraction.from_str("1.5") // 3/2
/// let f3 = @amor2025/fraction/fraction.from_float(0.25) // 1/4
/// inspect(f1.numerator, content="3")
/// inspect(f1.denominator, content="4")
/// let sum = f1 + f2 // 加法运算
/// let product = f1 * f3 // 乘法运算
/// inspect(sum.to_string(), content="9/4")
/// inspect(product.to_double(), content="0.1875")
/// ```
///
/// 注意：
///
/// * 分数的分子和分母必须是整数。
/// * 分母不能为零。
/// * 除法运算时，如果分子为零，会引发恐慌。
///
/// 方法：
///
/// * `new(numerator : Int, denominator : Int) -> Fraction` : 创建一个新的分数。
/// * `from_str(s : String) -> Fraction` : 从字符串解析分数，如 `"3/4"` 或 `"1.5"`。
/// * `from_float(f : Float) -> Fraction` : 从浮点数解析分数，如 `0.25`。
/// * `to_string(self : Fraction) -> String` : 将分数转换为字符串表示，如 `"3/4"`。
pub struct Fraction {
  numerator : Int
  denominator : Int
} derive(Show, Default, Eq)

///| 分数转换为字符串
pub fn to_string(self : Fraction) -> String {
  "\{self.numerator}/\{self.denominator}"
}


///|最大公约数计算函数
fn gcd(a : Int, b : Int) -> Int {
  if b == 0 {
    a.abs()
  } else {
    gcd(b, a % b)
  }
}


///|分数构造函数，自动约分并确保分母为正数
pub fn new(numerator : Int, denominator : Int) -> Fraction {
  if denominator == 0 {
    panic() // "分母不能为零" 
  }
  let g = gcd(numerator, denominator)
  let mut num = numerator / g
  let mut den = denominator / g
  if den < 0 {
    num = -num
    den = -den
  }
  Fraction::{ numerator: num, denominator: den }
}

///| 分数加法
///
pub impl Add for Fraction with op_add(self : Fraction, other : Fraction) -> Fraction {
  let new_num = self.numerator * other.denominator +
    other.numerator * self.denominator
  let new_den = self.denominator * other.denominator
  new(new_num, new_den)
}


///| 分数减法
///
pub impl Sub for Fraction with op_sub(self : Fraction, other : Fraction) -> Fraction {
  let new_num = self.numerator * other.denominator -
    other.numerator * self.denominator
  let new_den = self.denominator * other.denominator
  new(new_num, new_den)
}

///| 分数乘法
pub impl Mul for Fraction with op_mul(self : Fraction, other : Fraction) -> Fraction {
  let new_num = self.numerator * other.numerator
  let new_den = self.denominator * other.denominator
  new(new_num, new_den)
}


///| 分数除法
pub impl Div for Fraction with op_div(self : Fraction, other : Fraction) -> Fraction {
  if other.numerator == 0 {
    panic() // 除数不能为零 Divisor cannot be zero
  }
  let new_num = self.numerator * other.denominator
  let new_den = self.denominator * other.numerator
  new(new_num, new_den)
}

///| 从字符串解析分数，支持整数、小数、分数格式 
pub fn from_str(s : String) -> Fraction {
  let trimmed = s.trim(" \t\n\r")
  
  // 检查是否为分数格式 (如 "3/4")
  if trimmed.contains("/") {
    let parts = trimmed.split("/").to_array()
    if parts.length() == 2 {
      let num_str = parts[0].trim(" \t\n\r").to_string()
      let den_str = parts[1].trim(" \t\n\r").to_string()

 
      match (@convert.str_to_int(num_str), @convert.str_to_int(den_str)) {
        (Some(num), Some(den)) => new(num, den)
        _ => panic() // "无效的分数格式"
      }
    } else {
      panic() // "无效的分数格式"
    }
  }
  // 检查是否为小数格式 (如 "3.14")
  // Check if it's decimal format (like "3.14")
  else if trimmed.contains(".") {
    from_decimal_str(trimmed.to_string())
  }
  // 整数格式
  // Integer format
  else {
    match @convert.str_to_int(trimmed.to_string()) {
      Some(num) => new(num, 1)
      None => panic() // "无效的数字格式"
    }
  }
}

///| 从小数字符串转换为分数
///
fn from_decimal_str(s : String) -> Fraction {
  let parts = s.split(".").to_array()
  if parts.length() != 2 {
    panic() // "无效的小数格式"
  }
  
  let integer_part = parts[0].to_string()
  let decimal_part = parts[1].to_string()
  


  match @convert.str_to_int(integer_part){
    Some(int_val) => {
      let decimal_places = decimal_part.length()
      match @convert.str_to_int(decimal_part){
        Some(dec_val) => {
          let denominator = pow_10(decimal_places)
          let numerator = int_val * denominator + (if int_val >= 0 { dec_val } else { -dec_val })
          new(numerator, denominator)
        }
        None => panic() // "无效的小数部分"
      }
    }
    None => panic() // "无效的整数部分"
  }
}

///| 计算10的n次方
///
fn pow_10(n : Int) -> Int {
  let mut result = 1
  let mut i = 0
  while i < n {
    result = result * 10
    i = i + 1
  }
  result
}

///| 从浮点数转换为分数
///
pub fn from_float(f : Double) -> Fraction {
  // 处理特殊情况
  if f.is_nan() || f.is_inf() {
    panic() // "无法转换NaN或无穷大"
  }
  
  // 转换为字符串然后解析
  let s = f.to_string()
  from_str(s)
}

///| 分数的平方
///
pub fn square(self : Fraction) -> Fraction {
  new(self.numerator * self.numerator, self.denominator * self.denominator)
}

///| 分数的开方（返回近似分数）
///
pub fn sqrt(self : Fraction) -> Fraction {
  if self.numerator < 0 {
    panic() // "负数不能开方"
  }
  
  // 使用牛顿法求近似值
  let value = self.to_double()
  let sqrt_value = value.sqrt()
  from_float(sqrt_value)
}

///| 转换为浮点数
///
pub fn to_double(self : Fraction) -> Double {
  self.numerator.to_double() / self.denominator.to_double()
}

///| 取倒数（分子分母交换）
///
pub fn reciprocal(self : Fraction) -> Fraction {
  if self.numerator == 0 {
    panic() // "零没有倒数"
  }
  new(self.denominator, self.numerator)
}

///| 绝对值
///
pub fn abs(self : Fraction) -> Fraction {
  new(self.numerator.abs(), self.denominator)
}

///| 幂运算（支持整数指数）
///
pub fn pow(self : Fraction, exponent : Int) -> Fraction {
  if exponent == 0 {
    return new(1, 1)
  }
  if exponent > 0 {
    new(int_pow(self.numerator, exponent), int_pow(self.denominator, exponent))
  } else {
    // 负指数取倒数
    let positive_exp = (-exponent)
    new(int_pow(self.denominator, positive_exp), int_pow(self.numerator, positive_exp))
  }
}

///| 整数幂运算
///
fn int_pow(base : Int, exp : Int) -> Int {
  if exp == 0 {
    1
  } else if exp == 1 {
    base
  } else {
    let mut result = 1
    let mut b = base
    let mut e = exp
    while e > 0 {
      if e % 2 == 1 {
        result = result * b
      }
      b = b * b
      e = e / 2
    }
    result
  }
}

///| 转换为带分数形式（整数部分 + 真分数）
///
pub fn to_mixed_number(self : Fraction) -> (Int, Fraction) {
  let integer_part = self.numerator / self.denominator
  let remainder = self.numerator % self.denominator
  let fractional_part = new(remainder.abs(), self.denominator)
  (integer_part, fractional_part)
}

///| 转换为百分比字符串
///
pub fn to_percentage(self : Fraction) -> String {
  let percent = self.to_double() * 100.0
  "\{percent}%"
}

///| 判断是否为真分数（分子小于分母）
///
pub fn is_proper(self : Fraction) -> Bool {
  self.numerator.abs() < self.denominator
}

///| 判断是否为假分数（分子大于等于分母）
///
pub fn is_improper(self : Fraction) -> Bool {
  self.numerator.abs() >= self.denominator
}

///| 约分到最简形式（已经是约分后的，这里只是明确返回自身）
///
pub fn reduce(self : Fraction) -> Fraction {
  new(self.numerator, self.denominator)
}


// 比较运算符实现

///| 分数小于比较
pub impl Compare for Fraction with compare(self : Fraction, other : Fraction) -> Int {
  let left = self.numerator * other.denominator
  let right = other.numerator * self.denominator
  if left < right {
    -1
  } else if left > right {
    1
  } else {
    0
  }
}

///| 分数小于比较
pub fn op_lt(self : Fraction, other : Fraction) -> Bool {
  self.numerator * other.denominator < other.numerator * self.denominator
}

///| 分数小于等于比较
pub fn op_le(self : Fraction, other : Fraction) -> Bool {
  self.numerator * other.denominator <= other.numerator * self.denominator
}

///| 分数大于比较
pub fn op_gt(self : Fraction, other : Fraction) -> Bool {
  self.numerator * other.denominator > other.numerator * self.denominator
}

///| 分数大于等于比较
pub fn op_ge(self : Fraction, other : Fraction) -> Bool {
  self.numerator * other.denominator >= other.numerator * self.denominator
}

///| 获取分数的符号（正数返回1，负数返回-1，零返回0）
///
pub fn sign(self : Fraction) -> Int {
  if self.numerator > 0 {
    1
  } else if self.numerator < 0 {
    -1
  } else {
    0
  }
}

///| 获取相反数
///
pub fn negate(self : Fraction) -> Fraction {
  new(-self.numerator, self.denominator)
}


